package nig.ssh;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import java.io.ByteArrayOutputStream;
import static nig.ssh.Util.*;


/**
 * Simple generic wrapper for the public and private components of a
 * PEM-formatted public key pair. The two components are accessible as char[].
 * Use the factory methods to generate the algorithm-specific key pairs.<br><br>
 * 
 * Note: This class contains sensitive data and is not protected in anyway,
 *       so only supply instances to code that need it, and remember to call
 *       {@link #dispose()} when you're done.
 * 
 * @author King Lung Chiu
 */
public final class KeyPair
{
   /**
    * Public key of this key pair.
    */
   public final char[] publicPEM;

   /**
    * Private key of this key pair.
    */
   public final char[] privatePEM;

   private KeyPair(char[] pub, char[] prv) {
      publicPEM = pub;
      privatePEM = prv;
   }

   // NOTE: Use this only after the JSch library conflict issue (with MF-supplied
   //       ones) is fixed, else will get runtime errors.
   //       ie. genRSA2048() & genRSA4096() won't be usable either
   //
   //       For testing purposes, use defaultKeyPair(...) for the time being.
   private static KeyPair genRSA(int size, String pubKeyComment) throws JSchException {
      com.jcraft.jsch.KeyPair kpair = com.jcraft.jsch.KeyPair.genKeyPair(
         new JSch(), com.jcraft.jsch.KeyPair.RSA, size);
      ByteArrayOutputStream baosPrv = new ByteArrayOutputStream();
      kpair.writePrivateKey(baosPrv);
      ByteArrayOutputStream baosPub = new ByteArrayOutputStream();
      kpair.writePublicKey(baosPub, pubKeyComment);

      KeyPair kp = new KeyPair(
         asChars(baosPub.toByteArray()),
         asChars(baosPrv.toByteArray()));

      kpair.dispose();
      clear(baosPub);
      clear(baosPrv);
      return kp;         
   }

   /**
    * Generate a 2048-bit RSA key pair.<br><br>
    * 
    * Note: Where possible, clients should use a longer key,
    *       eg. via {@link KeyPair#genRSA4096(java.lang.String)}.
    * 
    * @param pubKeyComment
    *    Comment to append to the SSH public key. Usually in the form of
    *    username@originating.host
    * 
    * @return
    *    A newly generated RSA {@link KeyPair}.
    * 
    * @throws JSchException 
    */
   public static KeyPair genRSA2048(String pubKeyComment) throws JSchException {
      return genRSA(2048, pubKeyComment);
   }

   /**
    * Generate a 4096-bit RSA key pair.
    * 
    * @param pubKeyComment
    *    Comment to append to the SSH public key. Usually in the form of
    *    username@originating.host
    * 
    * @return
    *    A newly generated RSA {@link KeyPair}.
    * 
    * @throws JSchException 
    */
   public static KeyPair genRSA4096(String pubKeyComment) throws JSchException {
      return genRSA(4096, pubKeyComment);
   }
   
   /**
    * Provide the default pair of RSA keys.<p><p>
    * 
    * Note this is a hard-coded pair of keys and may change in the future.
    * Everyone has access to this pair, so use this only for testing purposes.
    * 
    * @param pubKeyComment
    *    Comment to append to the SSH public key. Usually in the form of
    *    username@originating.host
    * 
    * @return
    *    The defaut, hard-coded set of RSA keys.
    */
   public static KeyPair defaultPair(String pubKeyComment) {
      return new KeyPair(
         (defaultPublicKey + pubKeyComment).toCharArray(),
         defaultPrivateKey.toCharArray());      
   }

   /**
    * Clear the private component of this key pair. For security reasons,
    * clients should always call this when they're finished with this key pair.
    */
   public void dispose() {
      clear(privatePEM);
   }
   
   
   private static final String defaultPrivateKey = new StringBuilder()
      .append("-----BEGIN RSA PRIVATE KEY-----\n")
      .append("MIIEowIBAAKCAQEAgp79OI6Nf/clKSrwSc9tGD4EiM78w1WFKU2snGonV+WvbsdU\n")
      .append("u5v5IeIWUCQwdrrk9D8cRFnuBcv6ivpvtDtsl6/15NYsqfIGrA1ivCOMXtBPrlB3\n")
      .append("xzQUo/GdoVCsolAawok69ak7EZuoIa56tpshVewIdAkT28JATqixWfxPpAPy9zpG\n")
      .append("COT14ZNGzBPXW/N83iaEdpmVus2kfA05QdkzG7VAN8l+r8duGibqQGVk/ICcMGR4\n")
      .append("58+ewbCDyY1DU4/h0hoJ9EPy3uI+CA0howSpeibtpMPOolSn6XViuyn4BjoLexfH\n")
      .append("zVvdcP39PEHJ8niw9QDk7rQyncPFeHi6lcNMcQIDAQABAoIBAGAbUv02Be7NjU4J\n")
      .append("BduI/yADIZr3kQq39c46FHLRuDj4CmhbyYBwdpHzo687sVzqjmMXvFieQn+JYcK4\n")
      .append("GVBnGLNTCH1jCGHSbg5RmwAKt9FbPAVpt3eeXkFyGSUEEsEqZ0YTaoouBgQin0aI\n")
      .append("9kk9Qv3ROTcHJtFez6oQfM1U09Q89kNXsqIZ/k++ZdZH3TcP1wK1H2CES+Whwc4w\n")
      .append("lZMHM6MhUD25UCLHkccIBM3ii2EynsS+1bEp5k+d1o/1NnrpQb0GcAoqZszyyqfZ\n")
      .append("wbfsRLayZZAdxW9mpBRyDy4eRUnDGr4vf9/iMIv1O/4k3eeBfLT67fYgDzj7l0Tj\n")
      .append("kWi+YEECgYEAvvOcts1B0jBDLok+yZVGn+ibY5OJAg97onyd9ZGizAVJO8VUYwEZ\n")
      .append("lu29nKuSzRHyK7lGlHJNLJmH+JlQescYEglCZJRHN+lT01lrNr5qXZFh+DgjyFfd\n")
      .append("YRQbWHkfLig8gP70G8ts5gyDDCQsD+DiiUzXKSwCxBLXh0U5Ni146JUCgYEArx4b\n")
      .append("is5qzFGI5IbMtfMd2VB0PwiMS6s/c1WpTbwqDOg6hQPUs+bJQNR8GQiKgwAJX+0C\n")
      .append("soh/KDnunx6XbUwEpTcplw8Fyv7vJhjaT+Hqm5Isdioz0aP/GtvGXe1IFCv3h0rs\n")
      .append("coZkhs8eNFSfyCVsmEz/sRgtsp6oSVNHNrQE8W0CgYAmHQflsNh3dKykKD7BC6ua\n")
      .append("FVqWqIcLQz3hM9BviI8e+9sfNAbg8AJEjtVu5QwbJH7a3VNKI/plcYujQi6/Iuga\n")
      .append("CYEYBESm00qo/8sXlTAz1uXgHox925PTYakHor1ngB57fOgKeDMXQ94QWVP2I2P0\n")
      .append("FcNIc4Fl04DzfgyqVK8ydQKBgF8XtlUV6iCxVeji2l8jed38NmPUPHsKrxXuOlWg\n")
      .append("DCWeJcj9X4+hjz/JIuplHPIuHukcRw6z2Hj7nHyDnC8ZzJv67Ha/DaJB9ZN2g3ZF\n")
      .append("c6SvJ72zBRieOXVYSsvOggmSJoQtR2CZYhVie0Bng6ynxeSeS2rbelU4mqHWuyEV\n")
      .append("eGmxAoGBAL4bEv/is+MN+6kSTy9PCLhws+5eyBDHOnTebvlbao9zkNE4Nx8ERm3w\n")
      .append("p2sD1zP2Ls/sNh4C0h78urhebdyDrZ996iYVxVenp+PVMeoNLjV4k9kCw670I4T/\n")
      .append("264fEByHHU7y8KWuVvy+LV7AxTn4/PBWXxOl5aKxFCxXWu33+RJU\n")
      .append("-----END RSA PRIVATE KEY-----\n")
      .toString();   
   private static final String defaultPublicKey = 
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCCnv04jo1/9yUpKvBJz20YPgSIzvzDVYUpTaycaidX5a9ux1S7m/kh4hZQJDB2uuT0PxxEWe4Fy/qK+m+0O2yXr/Xk1iyp8gasDWK8I4xe0E+uUHfHNBSj8Z2hUKyiUBrCiTr1qTsRm6ghrnq2myFV7Ah0CRPbwkBOqLFZ/E+kA/L3OkYI5PXhk0bME9db83zeJoR2mZW6zaR8DTlB2TMbtUA3yX6vx24aJupAZWT8gJwwZHjnz57BsIPJjUNTj+HSGgn0Q/Le4j4IDSGjBKl6Ju2kw86iVKfpdWK7KfgGOgt7F8fNW91w/f08QcnyeLD1AOTutDKdw8V4eLqVw0xx ";
}